msg_tool\scripts\softpal\img\pgd/
ge.rs

1use super::base::*;
2use crate::ext::io::*;
3use crate::scripts::base::*;
4use crate::types::*;
5use crate::utils::struct_pack::*;
6use anyhow::Result;
7use std::io::{Read, Seek};
8
9#[derive(Debug)]
10pub struct PgdGeBuilder {}
11
12impl PgdGeBuilder {
13    pub fn new() -> Self {
14        Self {}
15    }
16}
17
18impl ScriptBuilder for PgdGeBuilder {
19    fn default_encoding(&self) -> Encoding {
20        Encoding::Cp932
21    }
22
23    fn build_script(
24        &self,
25        buf: Vec<u8>,
26        _filename: &str,
27        _encoding: Encoding,
28        _archive_encoding: Encoding,
29        config: &ExtraConfig,
30        _archive: Option<&Box<dyn Script>>,
31    ) -> Result<Box<dyn Script>> {
32        Ok(Box::new(PgdGe::new(MemReader::new(buf), config)?))
33    }
34
35    fn extensions(&self) -> &'static [&'static str] {
36        &["pgd"]
37    }
38
39    fn script_type(&self) -> &'static ScriptType {
40        &ScriptType::SoftpalPgdGe
41    }
42
43    fn is_image(&self) -> bool {
44        true
45    }
46
47    fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
48        if buf_len >= 4 && buf.starts_with(b"GE \0") {
49            return Some(20);
50        }
51        None
52    }
53
54    fn can_create_image_file(&self) -> bool {
55        true
56    }
57
58    fn create_image_file<'a>(
59        &'a self,
60        data: ImageData,
61        mut writer: Box<dyn WriteSeek + 'a>,
62        options: &ExtraConfig,
63    ) -> Result<()> {
64        let header = PgdGeHeader {
65            offset_x: 0,
66            offset_y: 0,
67            width: data.width,
68            height: data.height,
69            canvas_width: data.width,
70            canvas_height: data.height,
71            mode: 3,
72            _unk: 0,
73        };
74        writer.write_all(b"GE \0")?;
75        header.pack(&mut writer, false, Encoding::Utf8)?;
76        PgdWriter::new(data, options.pgd_fake_compress)
77            .with_method(3)
78            .pack_ge(&mut writer)?;
79        Ok(())
80    }
81}
82
83#[derive(Debug)]
84pub struct PgdGe {
85    header: PgdGeHeader,
86    data: ImageData,
87    fake_compress: bool,
88}
89
90impl PgdGe {
91    pub fn new<T: Read + Seek>(mut input: T, config: &ExtraConfig) -> Result<Self> {
92        let mut magic = [0u8; 4];
93        input.read_exact(&mut magic)?;
94        if &magic != b"GE \0" {
95            return Err(anyhow::anyhow!("Not a valid PGD GE image"));
96        }
97        let header = PgdGeHeader::unpack(&mut input, false, Encoding::Utf8)?;
98        let reader = PgdReader::with_ge_header(input, &header)?;
99        let data = reader.unpack_ge()?;
100        Ok(Self {
101            header,
102            data,
103            fake_compress: config.pgd_fake_compress,
104        })
105    }
106}
107
108impl Script for PgdGe {
109    fn default_output_script_type(&self) -> OutputScriptType {
110        OutputScriptType::Json
111    }
112
113    fn default_format_type(&self) -> FormatOptions {
114        FormatOptions::None
115    }
116
117    fn is_image(&self) -> bool {
118        true
119    }
120
121    fn export_image(&self) -> Result<ImageData> {
122        Ok(self.data.clone())
123    }
124
125    fn import_image<'a>(
126        &'a self,
127        data: ImageData,
128        mut file: Box<dyn WriteSeek + 'a>,
129    ) -> Result<()> {
130        let mut header = self.header.clone();
131        if data.height != self.data.height {
132            return Err(anyhow::anyhow!(
133                "Image height does not match: expected {}, got {}",
134                self.data.height,
135                data.height
136            ));
137        }
138        if data.width != self.data.width {
139            return Err(anyhow::anyhow!(
140                "Image width does not match: expected {}, got {}",
141                self.data.width,
142                data.width
143            ));
144        }
145        header.mode = 3;
146        file.write_all(b"GE \0")?;
147        header.pack(&mut file, false, Encoding::Utf8)?;
148        PgdWriter::new(data, self.fake_compress)
149            .with_method(3)
150            .pack_ge(&mut file)?;
151        Ok(())
152    }
153}